www.gusucode.com > VC++ IP包流量分析程序 > VC++ IP包流量分析程序/gusucode/IPanalyser/ARP.cpp
//Download by http://www.NewXing.com // ARP.cpp: implementation of the ARP class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "IPAnalyser.h" #include "ARP.h" #pragma comment(lib,"wpcap.lib") #pragma comment(lib, "ws2_32.lib") #include <pcap.h> #include <string> #include <map> #include <remote-ext.h> using namespace std; #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// unsigned char* globalLocalMac; //全局本机mac地址 pcap_if_t* globalAdapter = 0; //当前适配器 bool nThreadSignal = false; //活动主机线程信号 bool nIPThreadSignal = false; //IP捕获信号 CString selectedIP; //所选IP int runTime; //运行时间 map<CString, PacketInfo> infoMap; //接收包信息 DWORD startTime; //IP包捕获开始时间 DWORD endTime; //IP包捕获结束时间 ARP::ARP() { } ARP::~ARP() { } //格式化IP地址和子网掩码地址 char* ARP::IpToStr(unsigned long ulIP) { static char output[12][3 * 4 + 3 + 1]; static short which; unsigned char* chIP; chIP = (unsigned char*)&ulIP; which = (which + 1 == 12 ? 0 : which + 1); sprintf(output[which], "%d.%d.%d.%d", chIP[0], chIP[1], chIP[2], chIP[3]); return output[which]; } //格式化Mac地址 CString ARP::MacToStr(unsigned char* macAddress) { CString strMAC; strMAC.Format("%02X-%02X-%02X-%02X-%02X-%02X",macAddress[0],macAddress[1],macAddress[2],macAddress[3],macAddress[4],macAddress[5]); return strMAC; } //填充ARP包,把自己作为目的,构建一个广播ARP请求包,伪造请求来自.112.112.112 unsigned char* ARP::FillRequestARPPacket(unsigned char* sourceMAC, unsigned char* arpSourceMAC, unsigned long sourceIP, unsigned long destIP, int size) { static arp_packet packet; //创建广播ARP包 static const arp_packet defaultPacket = {ETH_HRD_DEFAULT, ARP_HRD_DEFAULT}; memcpy(&packet, &defaultPacket, sizeof(defaultPacket)); //填充源MAC地址 memcpy(packet.eth.source_mac, sourceMAC, 6); //ehter源MAC memcpy(packet.arp.sour_addr, arpSourceMAC, 6); //arp源MAC packet.arp.sour_ip = sourceIP; //源IP地址 packet.arp.dest_ip = destIP; //目的IP地址 return (unsigned char*)&packet; } //获取本机Mac地址 unsigned char* ARP::GetLocalMac(char *adapterName, unsigned long localIP, bool &myMacSignal) { pcap_t* adapterHandle; char errBuff[PCAP_ERRBUF_SIZE+1]; //适配器异常检查 if((adapterHandle = pcap_open_live(adapterName, 60, 1, 100, errBuff)) == NULL) { MessageBox(NULL, "无法打开适配器!", NULL, MB_OK); return NULL; } struct pcap_pkthdr* header; const u_char* pktData; unsigned short arpOperation; static unsigned char arpSourceMAC[6]; unsigned long arpSourceIP = 0; unsigned long arpDestIP = 0; unsigned char sourcMAC[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; unsigned char* packet; //封arp包 packet = FillRequestARPPacket(sourcMAC, sourcMAC, SOURCE_IP, localIP, 60); int pcapnext = 0; //bool myMacSignal = false; while(!myMacSignal) { //发送arp包 pcap_sendpacket(adapterHandle, packet, 60) ; Sleep(10); //接收arp包 pcapnext = pcap_next_ex(adapterHandle, &header, &pktData); if(pcapnext == 0) { continue; } //获取接收的arp包信息 memcpy(&arpOperation, pktData + 20, 2); memcpy(arpSourceMAC, pktData + 22, 6); memcpy(&arpSourceIP, pktData + 28, 4); memcpy(&arpDestIP, pktData + 38, 4); //收到应答包 if(arpOperation == htons(ARP_REPLY) && arpSourceIP == localIP && arpDestIP == SOURCE_IP) { myMacSignal = true; pcap_close(adapterHandle); return arpSourceMAC; } Sleep(100); } pcap_close(adapterHandle); return arpSourceMAC; } //解析IP协议类型 char * GetProtocolType(BYTE protocolType) { switch (protocolType) { case 6: return "TCP"; case 17: return "UDP"; default: return "Unknown"; } } //arp包发送线程 UINT SendArpPacket(LPVOID pParam) { pcap_addr_t* address = 0; unsigned long localIP = 0; unsigned long destIP = 0; unsigned long snd_tpa = 0; int netsize = 0; pcap_t* adapterHandle; char errBuff[PCAP_ERRBUF_SIZE + 1]; if((adapterHandle = pcap_open_live(globalAdapter->name, 60, 0, 100, errBuff)) == NULL) { MessageBox(NULL, "该适配器无法打开", NULL, MB_OK); return 0; } unsigned char* requestPacket; ARP arp; //给本网卡的所有ip子网发arp报文 for(address = globalAdapter->addresses; address; address = address->next) { if(nThreadSignal == false) { break; } //获取IP地址 localIP = ((struct sockaddr_in *)address->addr)->sin_addr.s_addr; if(!localIP) { continue; } //填充报文 requestPacket = arp.FillRequestARPPacket(globalLocalMac, globalLocalMac, localIP, localIP, 60); //取子网大小 unsigned long nlNetMask = 0; nlNetMask = ((struct sockaddr_in *)(address->netmask))->sin_addr.s_addr; netsize = ~ntohl(nlNetMask); //子网大小255 destIP = ntohl(localIP & nlNetMask); //给该IP所在子网的所有IP发送报文 for(int i = 0; i < netsize; i++) { if(nThreadSignal == false) { break; } snd_tpa = htonl(destIP); memcpy(requestPacket + 38, &snd_tpa, 4); pcap_sendpacket(adapterHandle, requestPacket, 60); destIP++; Sleep(5); } } return 0; } //arp包接收线程 UINT ReceiveArpPacket(LPVOID pParam) { pcap_t* adapterHandle; char errBuff[PCAP_ERRBUF_SIZE + 1]; if((adapterHandle = pcap_open_live(globalAdapter->name, 60, 0, 100, errBuff)) == NULL) { MessageBox(NULL, "无法连接适配器!", NULL, MB_OK); return -1; } ARP arp; string packetInfo; char* filter = "ether proto\\arp"; bpf_program fcode; int res; unsigned short operation = 0; unsigned char sourceMAC[6]; unsigned long sourceIP = 0; unsigned long netmask = 0; struct pcap_pkthdr* header; const u_char* pktData; if(pcap_compile(adapterHandle, &fcode, filter, 1, (unsigned long)(0xFFFF0000)) < 0) { MessageBox(NULL, "Filter is wrong", NULL, MB_OK); return -1; } if(pcap_setfilter(adapterHandle, &fcode) < 0) { MessageBox(NULL, "Filter is not right with the Adapter!", NULL, MB_OK); return -1; } //获取报文 while(true) { if(nThreadSignal == false) { break; } packetInfo = ""; res = pcap_next_ex(adapterHandle, &header, &pktData);//获取报文信息 if(!res) { continue; } memcpy(&operation, pktData + 20, 2); //获取操作符 memcpy(sourceMAC, pktData + 22, 6); //获取源MAC地址 memcpy(&sourceIP, pktData + 28, 4); //获取源IP地址 //格式化IP-MAC地址 packetInfo += arp.IpToStr(sourceIP); packetInfo += ":"; packetInfo += arp.MacToStr(sourceMAC); //将MAC-IP列表显示更新 if(operation == htons(ARP_REPLY)) { AfxGetApp()->m_pMainWnd->SendMessage(WM_RECEIVE, WPARAM(&packetInfo), 0); } } return 0; } //IP包分析线程 UINT AnaylsisPackets(LPVOID pParam) { pcap_t * handle; //打开适配器 char errBuff[PCAP_ERRBUF_SIZE+1]; if((handle = pcap_open_live( globalAdapter->name, //网络设备名 65535, //允许截获数据包的最大长度 PCAP_OPENFLAG_PROMISCUOUS, //混杂模式设置 1000, //读取数据超时时间 errBuff))==NULL) //错误信息 { MessageBox(NULL, "不能打开适配器", NULL, MB_OK); } //获取子网掩码 unsigned int netMask; if(globalAdapter->addresses != NULL) { netMask = ((struct sockaddr_in *)(globalAdapter->addresses->netmask))->sin_addr.s_addr; } else { netMask = 0xffffff;//忽略子网掩码 } //限定过滤表达式 char packetFilter[] = "tcp or udp"; //过滤表达式 //编译过滤器 struct bpf_program fcode; if (pcap_compile(handle, &fcode, packetFilter, 1, netMask) < 0) { MessageBox(NULL, "无法编译通过滤器!", NULL, MB_OK); TRACE("无法编译通过滤器!%s", pcap_geterr(handle)); return 0; } //设置过滤器 pcap_setfilter(handle, &fcode); int res = 0; struct pcap_pkthdr *header; const u_char *pkt_data; DWORD nowTime; ARP arp; while(res >= 0) { res = pcap_next_ex(handle, &header, &pkt_data); //检查运行时间是否结束,若是则跳出循环 nowTime = GetTickCount(); if(runTime != 0) { if((nowTime - startTime) >= runTime) { nIPThreadSignal = false; endTime = nowTime; break; } } //检查用户是否结束该线程,若是则跳出循环 if(!nIPThreadSignal) { break; } if (res == 0) { continue; } //获取IP包内容 IPHeader *ipHeader; ipHeader = (IPHeader *)(pkt_data + 14); //若用户选择默认地址 bool flag = false; if (strcmp(LPCSTR(selectedIP), DEFAULTSETTING) == 0) { } //若该包发送或目的地址与用户所选IP相同,则记录该包信息 if(strcmp(arp.IpToStr(ipHeader->sourceAddr),LPCSTR(selectedIP)) == 0 || strcmp(arp.IpToStr(ipHeader->destAddr),LPCSTR(selectedIP)) == 0 || strcmp(LPCSTR(selectedIP), DEFAULTSETTING) == 0) { //记录该IP包信息 map<CString, PacketInfo>::iterator infoIterator; infoIterator = infoMap.begin(); //获取源地址、目的地址、协议类型 CString source( inet_ntoa(*(in_addr*)&ipHeader->sourceAddr) ); CString dest( inet_ntoa(*(in_addr*)&ipHeader->destAddr) ); CString type( GetProtocolType(ipHeader->protocol) ); //判断是udp/tcp,获取端口号 unsigned int ip_len = (ipHeader->version & 0xf) * 4; unsigned short sport; unsigned short dport; if ( ipHeader->protocol == 6)//TCP { // 获得TCP首部的位置 TCPHeader *tcp = (TCPHeader *) ((unsigned char*)ipHeader + ip_len); // 将网络字节序列转换成主机字节序列 sport = ntohs( tcp->sport ); //源端口号 dport = ntohs( tcp->dport ); //目的端口号 } else if(ipHeader->protocol == 17)//UDP { // 获得UDP首部的位置 UDPHeader *udp = (UDPHeader *) ((unsigned char*)ipHeader + ip_len); // 将网络字节序列转换成主机字节序列 sport = ntohs( udp->sport ); //源端口号 dport = ntohs( udp->dport ); //目的端口号 } //设置主键 //CString key = source + dest + (CString)sport + (CString)dport + type; CString str1; str1.Format("%d",sport); CString str2; str2.Format("%d",dport); CString key = source + dest + str1 + str2 + type; PacketInfo packetInfo; packetInfo.sourceIP = source; packetInfo.destIP = dest; packetInfo.sourcePort.Format("%d",sport); packetInfo.destPort.Format("%d",dport); packetInfo.protocolType = type; packetInfo.total = 1; infoIterator = infoMap.find(key); //插入键值 if(infoIterator == infoMap.end()) { infoMap[key] = packetInfo; } else { infoMap[key].total++; } } } AfxGetApp()->m_pMainWnd->SendMessage(WM_ANALYSIS, WPARAM(&infoMap), 0); return 0; }